package de.muyat.kablosuzizci.istemci;

import tr.muyat.kablosuzizci.istemci.yardimcilarmodulu.FormatHatasi;

/**
 * Bir koordinat ve bir de oryantasyondan meydana gelen pozisyon bilgisi.
 *
 * @author Dzhoshkun Ismail Shakir
 *
 */
public class Pozisyon {
	private Koordinat koordinat;
	private Oryantasyon oryantasyon;
	
	@SuppressWarnings("unused")
	private Pozisyon() {
		
	}
	
	public Pozisyon(float x, float y, float z, float azimuth, float pitch, float roll) {
		this.koordinat = new Koordinat(x, y, z);
		this.oryantasyon = new Oryantasyon(azimuth, pitch, roll);
	}
	
	public Pozisyon(Koordinat koordinat, Oryantasyon oryantasyon) {
		this.koordinat = koordinat;
		this.oryantasyon = oryantasyon;
	}

	/**
	 * @return x
	 */
	public float getX() {
		return this.koordinat.getX();
	}

	/**
	 * @return y
	 */
	public float getY() {
		return this.koordinat.getY();
	}

	/**
	 * @return z
	 */
	public float getZ() {
		return this.koordinat.getZ();
	}

	/**
	 * @return azimuth
	 */
	public float getAzimuth() {
		return this.oryantasyon.getAzimuth();
	}
	
	/**
	 * 
	 * @param dereceMi eger bu {@code true} ise, istenen aciyi derece cinsinden verir
	 * @return
	 */
	public float getAzimuth(boolean dereceMi) {
		return dereceMi ? (float) Math.toDegrees(getAzimuth()) : getAzimuth();
	}

	/**
	 * @return pitch
	 */
	public float getPitch() {
		return this.oryantasyon.getPitch();
	}

	/**
	 * 
	 * @param dereceMi eger bu {@code true} ise, istenen aciyi derece cinsinden verir
	 * @return
	 */
	public float getPitch(boolean dereceMi) {
		return dereceMi ? (float) Math.toDegrees(getAzimuth()) : getAzimuth();
	}

	/**
	 * @return roll
	 */
	public float getRoll() {
		return this.oryantasyon.getRoll();
	}

	/**
	 * 
	 * @param dereceMi eger bu {@code true} ise, istenen aciyi derece cinsinden verir
	 * @return
	 */
	public float getRoll(boolean dereceMi) {
		return dereceMi ? (float) Math.toDegrees(getAzimuth()) : getAzimuth();
	}

	/**
	 * @return bu pozisyonun koordinati
	 */
	public Koordinat getCoordinate() {
		return this.koordinat;
	}

	/**
	 * @return bu pozisyonun oryantasyonu
	 */
	public Oryantasyon getOrientation() {
		return this.oryantasyon;
	}

	/**
	 * 
	 * @return pozisyon bilgilerinin byte dizini olarak serilestirilmis hali
	 */
	public byte[] serilestir() {
		byte[] koordinatDizini = koordinat.serilestir();
		byte[] oryantasyonDizini = oryantasyon.serilestir();
		byte[] pozisyonDizini = new byte[koordinatDizini.length+oryantasyonDizini.length];
		System.arraycopy(koordinatDizini, 0, pozisyonDizini, 0, koordinatDizini.length);
		System.arraycopy(oryantasyonDizini, 0, pozisyonDizini, koordinatDizini.length, oryantasyonDizini.length);
		return pozisyonDizini;
	}
	
	/**
	 * 
	 * @param serilestirilmisPozisyon
	 * @return parametre olarak girilen byte dizininden elde edilen obje
	 * @throws FormatHatasi
	 */
	public static Pozisyon seridenOku(byte[] serilestirilmisPozisyon) throws FormatHatasi {
		Koordinat koordinat = Koordinat.seridenOku(serilestirilmisPozisyon, 0);
		Oryantasyon oryantasyon = Oryantasyon.seridenOku(serilestirilmisPozisyon, Koordinat.DIZIN_BYTE_UZUNLUGU);
		return new Pozisyon(koordinat, oryantasyon);
	}
	
	/**
	 * Bu nesnenin butun degerleri {@code baska} bir nesneden kopyalanir. Surekli yeni
	 * nesne yaratmamak icin boyle bir hack gerekti.
	 * @param baska
	 */
	public void kopyala(Pozisyon baska) {
		this.koordinat.kopyala(baska.koordinat);
		this.oryantasyon.kopyala(baska.oryantasyon);
	}
}